package com.uam.web.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.uam.common.annotation.Log;
import com.uam.common.config.UAMConfig;
import com.uam.common.constant.CST;
import com.uam.common.exception.UamException;
import com.uam.db.mapper.AircraftMapper;
import com.uam.db.mapper.PointMapper;
import com.uam.db.mapper.TaskMapper;
import com.uam.db.model.entity.Aircraft;
import com.uam.db.model.entity.Point;
import com.uam.service.impl.RouteServiceImpl;
import com.uam.utils.*;
import com.uam.web.common.model.BusinessType;
import com.uam.web.common.model.Result;
import com.uam.db.model.entity.RoutQueryModel;
import com.uam.web.common.model.SysLayerConfig;
import com.uam.web.common.thread.RouteTop20Thread;
import com.uam.web.common.utils.ResourceUtils;
import com.uam.web.common.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * @author uam
 * @create 2023/12/4 15:01
 * @email uam@uam.com
 */
@Api(tags = "航线查询top2")
@RestController
@RequestMapping("/route")
@Slf4j
public class RouteController extends BaseController {
    static JSONObject jsonObjectStatic = null;

    static {

        String data = "{\"code\":0,\"cost\":0,\"data\":{\"total\":1,\"tracks\":[[{\"id\":\"1535508198\",\"task_id\":661,\"position\":[112.991936,28.251097],\"time\":1711090974,\"speed\":0,\"altitude\":0,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":104,\"communication_signal_num\":95,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"communication_signal_position\":[112.9849665851,28.2595809048],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[113.0385436222,28.2881683233],\"conflict_point\":false},{\"id\":\"1844992807\",\"task_id\":661,\"position\":[112.991936,28.251097],\"time\":1711090980,\"speed\":0,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":104,\"communication_signal_num\":95,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"communication_signal_position\":[112.9849665851,28.2595809048],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[113.0385436222,28.2881683233],\"conflict_point\":false},{\"id\":\"2145180055\",\"task_id\":661,\"position\":[112.991999,28.249999],\"time\":1711090984,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":103,\"communication_signal_num\":94,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"communication_signal_position\":[112.9849665851,28.2595809048],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[113.0385436222,28.2881683233],\"conflict_point\":false},{\"id\":\"769424898\",\"task_id\":661,\"position\":[112.97360514514861,28.25000115239046],\"time\":1711091044,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":108,\"communication_signal_num\":99,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"communication_signal_position\":[112.9849665851,28.2595809048],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"-2036657825\",\"task_id\":661,\"position\":[112.97176586714133,28.250675647155795],\"time\":1711091051,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":107,\"communication_signal_num\":98,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"conflict_task_ids\":[660],\"communication_signal_position\":[112.9656622084,28.2626970536],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":true},{\"id\":\"115822069\",\"task_id\":661,\"position\":[112.96992637413378,28.250001582868546],\"time\":1711091058,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":2,\"safe_distance\":20,\"positioning_accuracy\":122,\"conn_num\":109,\"communication_signal_num\":100,\"navigation_signal_num\":1,\"supervisory_signal_num\":8,\"communication_signal_position\":[112.9656622084,28.2626970536],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"-1473691078\",\"task_id\":661,\"position\":[112.957999,28.249999],\"time\":1711091097,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":111,\"communication_signal_num\":101,\"navigation_signal_num\":1,\"supervisory_signal_num\":9,\"communication_signal_position\":[112.9656622084,28.2626970536],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"1948832780\",\"task_id\":661,\"position\":[112.942999,28.234999],\"time\":1711091172,\"speed\":100,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":112,\"communication_signal_num\":102,\"navigation_signal_num\":1,\"supervisory_signal_num\":9,\"communication_signal_position\":[112.9521647274,28.2305567132],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"155387384\",\"task_id\":661,\"position\":[112.942378,28.23562],\"time\":1711091175,\"speed\":50,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":112,\"communication_signal_num\":102,\"navigation_signal_num\":1,\"supervisory_signal_num\":9,\"communication_signal_position\":[112.9521647274,28.2305567132],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"-513214377\",\"task_id\":661,\"position\":[112.9425,28.235714],\"time\":1711091178,\"speed\":0,\"altitude\":190,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":112,\"communication_signal_num\":102,\"navigation_signal_num\":1,\"supervisory_signal_num\":9,\"communication_signal_position\":[112.9521647274,28.2305567132],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false},{\"id\":\"452404052\",\"task_id\":661,\"position\":[112.9425,28.235714],\"time\":1711091184,\"speed\":0,\"altitude\":0,\"communication_signal\":1,\"navigation_signal\":3,\"supervisory_signal\":1,\"safe_distance\":20,\"positioning_accuracy\":147,\"conn_num\":112,\"communication_signal_num\":102,\"navigation_signal_num\":1,\"supervisory_signal_num\":9,\"communication_signal_position\":[112.9521647274,28.2305567132],\"navigation_signal_position\":[112.885912776,28.4728647593],\"supervisory_signal_position\":[112.9075298627,28.2591494698],\"conflict_point\":false}]]}}";
        jsonObjectStatic = JSON.parseObject(data).getJSONObject("data");
    }

    @Autowired
    private UAMConfig uamConfig;

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private AircraftMapper aircraftMapper;

    @Resource
    private PointMapper pointMapper;
    @Autowired
    @Qualifier("threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor executor;


    @Autowired
    private RouteServiceImpl routeService;


    @Log(title = "航线查询", businessType = BusinessType.QUERY_LOG)
    @ApiOperation(value = "航线查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "用户登录token", paramType = "header")
    })
    @GetMapping("/index")
    @ResponseBody
    public Result<List<RouteInfoVo>> route(@RequestParam(required = false) Integer size) {
        if (size == null || size <= 0) {
            throw new UamException("size 必须大于等于0！");
        }
        if (size > 100) {
            size = 100;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("size", size);
        JSONObject jsonObject1 = HttpUtils.getData(CST.URL + "/uam/route/track/top", jsonObject);

        if (jsonObject1 == null) {
            throw new UamException("暂时无航线飞行信息!");
        }

        JSONArray dataArray = jsonObject1.getJSONArray("tracks");
        if (dataArray == null || dataArray.size() == 0) {
            throw new UamException("暂时无航线飞行信息!");
        }

        int row = dataArray.size();
        Map<Long, Long> taskId = new HashMap<>(row);
        for (int i = 0; i < row; i++) {
            Long id = dataArray.getJSONArray(i).getJSONObject(0).getLong("task_id");
            taskId.put(id, id);
        }
        Map<Long, RoutQueryModel> taskMap = taskMapper.selectTaskAirplane(new ArrayList<>(taskId.values()));
        List<RouteInfoVo> routeVoList = new ArrayList<>(row);
        CountDownLatch countDownLatch = new CountDownLatch(row);
        for (int i = 0; i < row; i++) {
            executor.execute(new RouteTop20Thread(countDownLatch, dataArray.getJSONArray(i), taskMap, this, routeVoList));
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            log.error("线号中断异常", e);
        }
        return Result.createSuccess(routeVoList);
    }

    @PostMapping("/preview")
    @ResponseBody
    @Log(title = "航线预览")
    @ApiOperation(value = "航线预览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "用户登录token", paramType = "header", required = false),
            @ApiImplicitParam(name = "airplaneId", value = "飞行器Id"),
            @ApiImplicitParam(name = "transitPoints", value = "起点，途经点 终点"),
    })
    public Result<List<PreviewTrack>> preview(@RequestParam Long airplaneId, @RequestParam List<String> transitPoints) {
        Aircraft aircraft = aircraftMapper.selectById(airplaneId);
        if (aircraft == null) {
            throw new UamException("飞行器id不存在!");
        }

        if (transitPoints == null || transitPoints.size() < 2) {
            throw new UamException("起降点不能为空而且起降点必须大于等于2！");
        }

        LambdaQueryWrapper<Point> pointLambdaQueryWrapper = new LambdaQueryWrapper<>();
        pointLambdaQueryWrapper.in(Point::getPointId, transitPoints);
        List<Point> transitPointList = pointMapper.selectList(pointLambdaQueryWrapper);
        if (transitPointList == null || transitPointList.size() < 2) {
            throw new UamException("起降点不存在");
        }

        Map<String, Point> pointMap = new HashMap<>(32);
        transitPointList.forEach(a -> {
            pointMap.put(a.getPointId() + "", a);
        });

        JSONArray jsonArray = new JSONArray(32);
        transitPoints.forEach(a -> {
            Point point = pointMap.get(a);
            if (point == null) {
                throw new UamException("起降点或途经点不存在！，id：" + a);
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", point.getPointId());
            jsonObject.put("name", point.getPointName());
            JSONArray positionJA = new JSONArray();
            String position = point.getPosition();
            String[] split = position.split(",");
            for (String s : split) {
                positionJA.add(Float.valueOf(s));
            }
            jsonObject.put("position", positionJA);
            jsonArray.add(jsonObject);
        });
        JSONArray startPoint = jsonArray.getJSONObject(0).getJSONArray("position");
        JSONArray endPoint = jsonArray.getJSONObject(jsonArray.size() - 1).getJSONArray("position");

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("min_altitude", aircraft.getMinAltitude());
            jsonObject.put("max_altitude", aircraft.getMaxAltitude());
            jsonObject.put("safe_distance", aircraft.getFlightInterval());
            jsonObject.put("speed", aircraft.getAvgSpeed());
            jsonObject.put("max_speed", aircraft.getMaxSpeed());
            jsonObject.put("max_endurance", aircraft.getMaxEndurance());
            jsonObject.put("settings", URLEncoder.encode(jsonArray.toString(), "utf-8"));
            List<PreviewTrack> dataArray = HttpUtils.getDataArray(CST.URL + "/uam/route/preview", jsonObject, PreviewTrack.class);
            if (dataArray != null && dataArray.size() > 0) {
                for (int i = 0; i < dataArray.size(); i++) {
                    PreviewTrack previewTrack = dataArray.get(i);
                    JSONArray jsonArray1Data = previewTrack.getTrack();
                    jsonArray1Data.add(0, startPoint);
                    jsonArray1Data.add(endPoint);
                }
            }
            return Result.createSuccess(dataArray);
        } catch (Exception e) {
            log.error("获取航线预览错误！", e);
            throw new UamException("获取航线预览错误！");
        }
    }

    @PostMapping("/signal")
    @ResponseBody
    @Log(title = "信号强度统计", businessType = BusinessType.QUERY_LOG)
    @ApiOperation(value = "信号强度统计")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "用户登录token", paramType = "header", required = false, example = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDI3Mjk3MTIsImV4cCI6MTcwMjgxNjExMiwidXNlcklkIjo3LCJ1c2VyTmFtZSI6ImhlZ2wiLCJsb2dpbk5hbWUiOiJoZWdsIn0.A-Lb5oREUjl42j_-Txkl-_s0V_QkSPFj-4msan6BTD8"),
    })
    public Result<List<CectorCount>> signal() {
        SysLayerConfig sysLayerConfig = getSysLayerConfig(uamConfig.getSyslayerpath());
        Map<Integer, CectorCount> dataMap = new HashMap<>(16);
        SysLayerConfig.SysLayer sysLayer = sysLayerConfig.getSysLayerById(14);
        if (sysLayer != null) {
            String content = ResourceUtils.getFileContent(sysLayer.getPath());
            JSONArray jsonArray = JSONObject.parseObject(content).getJSONArray("features");
            if (jsonArray != null) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    try {
                        JSONObject jsonObject = jsonArray.getJSONObject(i).getJSONObject("properties").getJSONObject("extData");
                        Integer type = jsonObject.getInteger("type");
                        if (type != null) {
                            CectorCount cectorCount = dataMap.get(type);
                            if (cectorCount == null) {
                                cectorCount = new CectorCount(type);
                            }
                            Integer status = jsonObject.getInteger("status");
                            if (status != null) {
                                if (status == 0) {
                                    cectorCount.setDataCloseNum();
                                } else {
                                    cectorCount.setDataOpenNum();
                                }

                                dataMap.put(type, cectorCount);
                            }

                        }
                    } catch (Exception e) {
                        log.error("数据解析异常！");
                    }

                }

            }
        }
        return Result.createSuccess(new ArrayList<>(dataMap.values()));
    }


    @PostMapping("/export")
    @Log(title = "导出航线信息", businessType = BusinessType.QUERY_LOG)
    @ApiOperation(value = "导出航线信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "用户登录token", paramType = "header", required = false, example = ""),
            @ApiImplicitParam(name = "startTime", value = "开始时间：格式为：yyyyMMddHHmmss 例如：20231204170400", dataType = "String", dataTypeClass = String.class, example = "20231204170400"),
            @ApiImplicitParam(name = "endTime", value = "结束时间：格式为：yyyyMMddHHmmss 例如：20231204170400", dataType = "String", dataTypeClass = String.class, example = "20231224170400"),
    })
    public Result<Boolean> export(HttpServletResponse response,
                                  @RequestParam(required = true) String startTime,
                                  @RequestParam(required = true) String endTime) throws InterruptedException, IOException {
        Date sT = new Date();
        LocalDateTime start = null;
        LocalDateTime end = null;
        try {
            start = TimeUtils.getLocalDateTime(startTime.trim());
            end = TimeUtils.getLocalDateTime(endTime.trim());

        } catch (Exception e) {
            throw new UamException("起止时间格式错误！");
        }
        long sTime = TimeUtils.getDate(start).getTime();
        long eTime = TimeUtils.getDate(end).getTime();
        long times = eTime - sTime;
        if (times <= 0 || times > 604800000) {
            throw new UamException("开始时间不能大于起止时间，或 导出的数据不能超过7天！");
        }
        List<JSONObject> data = routeService.exportData(start, end);
        if (data != null && data.size() > 0) {
            CsvUtil.createJSONFile(data, null, "export_" + System.currentTimeMillis(), response);

        }
        log.info("导出花费时间：{},数量：{} 条", DateUtils.formatTime(sT, new Date()), data.size());
        return Result.createSuccess("正在组装数据，请耐心等待!");
    }
}
